package com.mingserve.raw.controller;

import com.mingserve.common.core.constant.CacheConstants;
import com.mingserve.common.core.domain.R;
import com.mingserve.common.core.utils.MathUtils;
import com.mingserve.common.redis.service.RedisService;
import com.mingserve.raw.domain.RawTime;
import com.mingserve.raw.domain.dto.SelectDto;
import com.mingserve.raw.domain.vo.FeatureVo;
import com.mingserve.raw.domain.vo.RawConnVo;
import com.mingserve.raw.domain.vo.RawTempVo;
import com.mingserve.raw.domain.vo.RawVo;
import com.mingserve.raw.service.IRawService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 传感器数据查询API
 *
 * @author lvwshuai
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/raw")
public class RawController
{
    private final IRawService rawService;
    private final RedisService redisService;

    /**
     * 测点最后一次上传的日期
     *
     * @param pointCode
     * @return
     */
    @GetMapping("/getLastDate")
    public R<Long> getLastDate(@RequestParam("pointCode") String pointCode) {
        Long ts = rawService.getLastDate(pointCode);
        return R.ok(ts);
    }

    /**
     * 获取测点某日期下的时间列表
     *
     * @param selectDto
     * @return
     */
    @GetMapping("/getTimeList")
    public R<List<Long>> getTimeList(SelectDto selectDto) {
        List<Long> list = rawService.getTimeList(selectDto);
        return R.ok(list);
    }

    /**
     * 获取测点某时间戳下的波形数据
     *
     * @param selectDto
     * @return
     */
    @GetMapping("/getVibRaw")
    public R<RawVo> getVibRaw(SelectDto selectDto) {
        return R.ok(rawService.getVibRaw(selectDto));
    }

    /**
     * 获取测点某时间戳下的FFT数据
     *
     * @param selectDto
     * @return
     */
    @GetMapping("/getVibFFT")
    public R<RawVo> getVibFFT(SelectDto selectDto) {
        return R.ok(rawService.getVibFFT(selectDto));
    }

    /**
     * 查询温度信息
     *
     * @param selectDto
     * @return
     */
    @GetMapping("/queryTemp")
    public R<RawTempVo> queryTemp(SelectDto selectDto) {
        return R.ok(rawService.queryRawTemp(selectDto));
    }

    /**
     * 查询统计包信息
     *
     * @param selectDto
     * @return
     */
    @GetMapping("/queryConn")
    public R<RawConnVo> queryConn(SelectDto selectDto) {
        return R.ok(rawService.queryConn(selectDto));
    }

    // 用来模拟存储任务进度，实际应用中可以使用数据库、缓存等持久化存储
    private final ConcurrentHashMap<String, Double> progressMap = new ConcurrentHashMap<>();

    /**
     * 上传原始数据并启动处理任务
     *
     * @param selectDto pointCode 多个以,隔开
     * @return 任务ID
     */
    @PostMapping("/uploadRaw")
    public R<Map<String, String>> uploadRaw(@RequestBody SelectDto selectDto)
    {
        // 生成任务 ID
        String taskId = generateTaskId();

        // 处理上传，并设置任务进度
        new Thread(() -> processUpload(selectDto, taskId)).start();

        // 返回任务 ID，前端可以用这个 ID 查询进度
        Map<String, String> map = new HashMap<>();
        map.put("taskId", taskId);
        return R.ok(map);
    }
    /**
     * 处理上传
     *
     * @param selectDto
     * @param taskId
     */
    private void processUpload(SelectDto selectDto, String taskId)
    {
        List<RawTime> list1 = rawService.queryRawTime(selectDto);
//        List<RawConn> list2 = rawService.queryRawConn(selectDto);
        int total = list1.size();// + list2.size();

        for (int i = 0; i < list1.size(); i++) {
            rawService.uploadRaw(list1.get(i));

            // 更新任务进度
            progressMap.put(taskId, MathUtils.round(100.0 * i / total, 2));
        }
//        for (int i = 0; i < list2.size(); i++) {
//            rawService.uploadRawConn(list2.get(i));
//            progressMap.put(taskId, MathUtils.round(100.0 * i / total, 2));
//        }
        // 处理完成后，将进度设为 100
        progressMap.put(taskId, 100d);
    }

    /**
     * 获取任务的处理进度
     *
     * @param taskId
     * @return 任务进度
     */
    @GetMapping("/progress/{taskId}")
    public R<Map<String, Double>> getProgress(@PathVariable("taskId") String taskId)
    {
        Double progress = progressMap.getOrDefault(taskId, 0d);
        Map<String, Double> map = new HashMap<>();
        map.put("progress", progress);
        if (progress == 100d) {
            progressMap.remove(taskId);
        }
        return R.ok(map);
    }

    /**
     * 删除原始数据并启动处理任务
     *
     * @param selectDto pointCode 多个以,隔开
     * @return 任务ID
     */
    @PostMapping("/deleteRaw")
    public R<Map<String, String>> deleteRaw(@RequestBody SelectDto selectDto)
    {
        // 生成任务 ID
        String taskId = generateTaskId();

        // 处理删除，并设置任务进度
        new Thread(() -> processDelete(selectDto, taskId)).start();

        // 返回任务 ID，前端可以用这个 ID 查询进度
        Map<String, String> map = new HashMap<>();
        map.put("taskId", taskId);
        return R.ok(map);
    }

    /**
     * 处理删除
     *
     * @param selectDto
     * @param taskId
     */
    private void processDelete(SelectDto selectDto, String taskId)
    {
        List<RawTime> list1 = rawService.queryRawTime(selectDto);
//        List<RawConn> list2 = rawService.queryRawConn(selectDto);
        int total = list1.size();// + list2.size();
        for (int i = 0; i < list1.size(); i++) {
            rawService.deleteRaw(list1.get(i));
            // 更新任务进度
            progressMap.put(taskId, MathUtils.round(100.0 * i / total, 2));
        }
//        for (int i = 0; i < list2.size(); i++) {
//            rawService.deleteRawConn(list2.get(i));
//            // 更新任务进度
//            progressMap.put(taskId, MathUtils.round(100.0 * i / total, 2));
//        }
        // 处理完成后，将进度设为 100
        progressMap.put(taskId, 100d);
    }

    // 生成一个唯一的任务 ID
    private String generateTaskId()
    {
        return "task-" + System.currentTimeMillis();
    }

    /**
     * 查询特征值
     *
     * @param selectDto
     * @return
     */
    @GetMapping("/queryFeature")
    public R<FeatureVo> queryFeature(SelectDto selectDto) {
        return R.ok(rawService.queryFeature(selectDto));
    }

    /**
     * 获取传感器当前配置
     *
     * @param deviceCode
     * @return
     */
    @GetMapping("/getSensorConfig")
    public R< Map<String, Object>> getLastRawConn(@RequestParam("deviceCode") String deviceCode) {
        String infoKey = CacheConstants.RAW_SENSOR_INFO_KEY + deviceCode;
        Map<String, Object> mapInfo = redisService.getCacheMap(infoKey);
        return R.ok(mapInfo);
    }
}